package yxy.cherry.data;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import yxy.apple.util.FileUtility;

public class DataMakerFomula {

	static String packageNameJS = "yxy.cherry.data.script";

	public void make() {
		try {
			File[] files = FileUtility.getFiles(System.getProperty("user.dir") + "/data/", ".js");
			for (File file : files) {
				makeJs(file, DataMaker.DIR, packageNameJS);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	void makeJs(File file, String dir, String packageName) throws Exception {
		String filename = FileUtility.getFileNameWithoutExtension(file);// 文件名

		String path = dir + "/" + packageName.replaceAll("\\.", "/");
		File output = new File(path + "/" + filename + ".java");
		if (output.exists()) {
			output.delete();
		}
		FileUtility.create(output);
		
		System.err.println("\r\nmakefile::" + filename);
		String content = assembleJsEnum(packageName, filename, file);
		FileOutputStream fos = new FileOutputStream(output);
		fos.write(content.getBytes("UTF-8"));
		fos.flush();
		fos.close();
		
		System.err.println(output.getName() + "文件生成");
	}

	private String assembleJsEnum(String packageName, String filename, File file) throws Exception {
		String content = assembleJsEnumContent(file);

		StringBuffer buffer = new StringBuffer();
		buffer.append("package " + packageName + ";");
		buffer.append("\r\n"); //
		buffer.append("\r\n"); //
		buffer.append("/** Js运算脚本 */\r\n" + //
				"public enum fomula {\r\n" + //
				content + //
				"	;\r\n" + //
				"\r\n" + //
				"	private String funcName;// 方法名\r\n" + //
				"	private Class<?> returnType;// 返回类型\r\n" + //
				"\r\n" + //
				"	private fomula(String funcName, Class<?> returnType) {\r\n" + //
				"		this.funcName = funcName;\r\n" + //
				"		this.returnType = returnType;\r\n" + //
				"	}\r\n" + //
				"\r\n" + //
				"	public Double doubleValue(Object... params) {\r\n" + //
				"		try {\r\n" + //
				"			if (returnType.equals(Double.class)) {\r\n" + //
				"				return FomulaScript.doubleValue(funcName, params);\r\n" + //
				"			}\r\n" + //
				"		} catch (Exception e) {\r\n" + //
				"			e.printStackTrace();\r\n" + //
				"		}\r\n" + //
				"		return Double.valueOf(0);\r\n" + //
				"	}\r\n" + //
				"\r\n" + //
				"	public int intValue(Object... params) {\r\n" + //
				"		try {\r\n" + //
				"			if (returnType.equals(Integer.class)) {\r\n" + //
				"				return FomulaScript.intValue(funcName, params);\r\n" + //
				"			}\r\n" + //
				"			if (returnType.equals(Double.class)) {\r\n" + //
				"				return FomulaScript.doubleValue(funcName, params).intValue();\r\n" + //
				"			}" + //
				"		} catch (Exception e) {\r\n" + //
				"			e.printStackTrace();\r\n" + //
				"		}\r\n" + //
				"		return 0;\r\n" + //
				"	}\r\n" + //
				"\r\n" + //
				"	public String string(Object... params) {\r\n" + //
				"		try {\r\n" + //
				"			if (returnType.equals(String.class)) {\r\n" + //
				"				return FomulaScript.stringValue(funcName, params);\r\n" + //
				"			}\r\n" + //
				"		} catch (Exception e) {\r\n" + //
				"			e.printStackTrace();\r\n" + //
				"		}\r\n" + //
				"		return null;\r\n" + //
				"	}\r\n" + //
				"}"); //
		return buffer.toString();
	}

	private String assembleJsEnumContent(File file) throws Exception {
		StringBuffer buffer = new StringBuffer();

		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("javascript");
		engine.eval(new FileReader(file));
		Invocable invocable = (Invocable) engine;

		BufferedReader reader = new BufferedReader(new FileReader(file));
		String line;
		String funcName = null;
		String comment = null;
		while ((line = reader.readLine()) != null) {
			if (line.startsWith("//")) {
				funcName = line.replaceAll("//", "").trim();
//				System.err.println(funcName);
				continue;
			}

			if (line.startsWith("/*")) {
				comment = line;
			}
			if (line.startsWith("function")) {
				String regex = "(?<=function).*?(?=\\()";
				Pattern p = Pattern.compile(regex);
				Matcher m = p.matcher(line);
				if (m.find()) {
					String func = m.group(0).trim();
//					System.err.println(func);
					try {
						Object result = invocable.invokeFunction(func, 0);
						buffer.append(fucnLine(funcName, func, comment, result));
					} catch (Exception e) {
						e.printStackTrace();
					}
					funcName = null;
					comment = null;
				} else {
					System.err.println("no match::" + line);
					continue;
				}
			}
		}
		reader.close();

		return buffer.toString();
	}

	private String fucnLine(String name, String func, String comment, Object obj) throws Exception {
		if (!(obj instanceof Double) && !(obj instanceof Integer) && !(obj instanceof String)) {
			throw new Exception();
		}
		if (comment == null) {
			String format = "\r\n	%s(\"%s\", %s.class),//\r\n";
			return String.format(format, name, func, obj.getClass().getSimpleName());
		}
		String format = "\r\n	%s\r\n" + "	%s(\"%s\", %s.class),//\r\n";
		return String.format(format, comment, name, func, obj.getClass().getSimpleName());
	}
}
